﻿/*

  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  
           http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is AST'r Framework.
  
  The Initial Developer of the Original Code is
  ALCARAZ Marc (aka eKameleon) <ekameleon@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2004-2011
  the Initial Developer. All Rights Reserved.
  
  Contributor(s) :
  
*/
package evideo.display.application 
{
    import graphics.Align;
    import graphics.display.Background;
    import graphics.display.DisplayObjects;

    import flash.display.DisplayObjectContainer;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.geom.Rectangle;
    import flash.media.Video;
    import flash.ui.Mouse;
    import flash.utils.Timer;
    
    /**
     * The video protector when the player is fullscreen.
     */
    public class VideoProtector extends Background 
    {
        /**
         * Creates a new VideoProtector instance.
         */
        public function VideoProtector()
        {
            _timer = new Timer(5000, 1) ;
            _timer.addEventListener( TimerEvent.TIMER , timerComplete ) ;
            dispose() ;
        }
        
        /**
         * Determinates the delay in ms of the protector to hide the mouse cursor and the video remote when the user don't move the mouse (default 5000 ms).
         */
        public function get delay():Number
        {
            return _timer.delay ;
        }
        
        /**
         * @private
         */
        public function set delay( value:Number ):void
        {
            _timer.delay = value ;
        }
        
        /**
         * The remote of the video player.
         */
        public function get remote():Background
        {
            return _remote ;
        }
        
        /**
         * @private
         */
        public function set remote( remote:Background ):void
        {
            if ( _remote && contains( _remote ) )
            {
                _remote.removeEventListener( MouseEvent.MOUSE_OVER , mouseOver ) ;
                _remote.removeEventListener( MouseEvent.MOUSE_OUT  , mouseOut  ) ;
                _remote.x = _remoteArea.x ;
                _remote.y = _remoteArea.y ;
                if ( _remoteParent )
                {
                    _remoteParent.addChild( _remote ) ;
                    _remoteParent = null ;
                }
                else
                {
                    removeChild( _remote ) ;
                }
            }
            _remote = remote ;
            if ( _remote )
            {
                _remote.addEventListener( MouseEvent.MOUSE_OVER , mouseOver , false, 0 , true ) ;
                _remote.addEventListener( MouseEvent.MOUSE_OUT  , mouseOut  , false, 0 , true ) ;
                _remoteArea.x = _remote.x      ;
                _remoteArea.y = _remote.y      ;
                _remoteParent = _remote.parent ;
                if ( _remoteParent )
                {
                    _remoteDepth = _remoteParent.getChildIndex( _remote ) ;
                }
                addChild( _remote ) ;
            }
            update() ;
        }
        
        /**
         * The video reference of the protector.
         */
        public function get video():Video
        {
            return _video ;
        }
        
        /**
         * @private
         */
        public function set video( video:Video ):void
        {
            if ( _video && contains( _video ) )
            {
                _video.x      = _videoArea.x      ;
                _video.y      = _videoArea.y      ;                _video.width  = _videoArea.width  ;                _video.height = _videoArea.height ;
                if ( _videoParent )
                {
                    if ( _videoDepth > -1 && _videoDepth < _videoParent.numChildren )
                    {
                        _videoParent.addChildAt( _video , _videoDepth ) ;
                    }
                    else
                    {
                        _videoParent.addChild( _video ) ;
                    }
                    _videoParent = null ;
                }
                else
                {
                    removeChild( _video ) ;
                }
                _videoDepth = -1 ;
            }
            _video = video ;
            if ( _video )
            {
                _videoArea.x      = _video.x      ;
                _videoArea.y      = _video.y      ;
                _videoArea.width  = _video.width  ;
                _videoArea.height = _video.height ;
                _videoParent      = _video.parent ;
                if ( _videoParent )
                {
                    _videoDepth = _videoParent.getChildIndex( _video ) ;
                }
                addChild( _video ) ;
            }
            update() ;
        }
        
        /**
         * Dispose the video protector.
         */
        public function dispose():void
        {
            remote       = null ;
            video        = null ;
            _remoteArea   = new Rectangle() ;
            _remoteDepth  = -1 ;
            _remoteParent = null ;
            _videoArea    = new Rectangle() ;
            _videoDepth   = -1 ;
            _videoParent  = null ;
        }
        
        /**
         * Hide the remote display and the mouse cursor.
         */
        public function hide():void
        {
            if ( remote )
            {
                remote.visible = false ;
            }
            Mouse.hide() ;
        }
        
        /**
         * Show the remote display and the mouse cursor.
         */
        public function show():void
        {
            if ( remote )
            {
                remote.visible = true ;
            }
            Mouse.show() ;
        }
        
        /**
         * Invoked after the draw() method in the update() method.
         */
        protected override function viewChanged():void
        {
            if ( _video )
            {
                _video.x      = 0 ;
                _video.y      = 0 ;
                _video.width  = w ;
                _video.height = h ;
            }
            if ( _remote )
            {
                DisplayObjects.align( _remote , new Rectangle(0,0,w,h) , Align.BOTTOM , null, "w" , "h" ) ;
            }
        }
        
        /**
         * Invoked when the display is removed from the stage.
         */
        protected override function addedToStage( e:Event = null ):void
        {
            stage.addEventListener( MouseEvent.MOUSE_MOVE , mouseMove ) ;
            _timer.start() ;
        }
        
        /**
         * Invoked when the mouse move.
         */
        protected function mouseMove( e:MouseEvent = null ):void
        {
            show() ;
            _timer.start() ;
        }
        
        /**
         * Invoked when the mouse is over the remote display.
         */
        protected function mouseOver( e:MouseEvent = null ):void
        {
            show() ;
            _isOver = true ;
            _timer.stop() ;
        }
        
        /**
         * Invoked when the mouse is out the remote display.
         */
        protected function mouseOut( e:MouseEvent = null ):void
        {
            show() ;
            _isOver = false ;
            _timer.start() ;
        }
        
        /**
         * Invoked when the display is removed from the stage.
         */
        protected override function removedFromStage( e:Event = null ):void
        {
            show() ;
            stage.removeEventListener( MouseEvent.MOUSE_MOVE , mouseMove ) ;
            if( _timer.running )
            {
                _timer.stop() ;
            }
        }
        
        /**
         * Invoked when the internal timer of the protector is complete.
         */
        protected function timerComplete( e:TimerEvent ):void
        {
            if ( !_isOver )
            {
                hide() ;
            }
        }
        
        /**
         * Indicates if the mouse is over the remote display.
         * @private
         */
        private var _isOver:Boolean ;
        
        /**
         * @private
         */
        private var _remote:Background ;
        
        /**
         * @private
         */
        private var _remoteArea:Rectangle ;
        
        /**
         * @private
         */
        private var _remoteDepth:int ;
        
        /**
         * @private
         */
        private var _remoteParent:DisplayObjectContainer ;
        
        /**
         * @private
         */
        private var _timer:Timer ;
        
        /**
         * @private
         */
        private var _video:Video ;
        
        /**
         * @private
         */
        private var _videoArea:Rectangle ;
        
        /**
         * @private
         */
        private var _videoDepth:int ;
        
        /**
         * @private
         */
        private var _videoParent:DisplayObjectContainer ;
    }
}
